package com.example.download;

import android.os.Handler;
import android.os.Message;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;

public class ClientActionController {

    ObjectInputStream ois;
    ObjectOutputStream oos;
    Map<String, Object> mReceivedMap;
    // 储存上一次获得的正确的map信息，以便当接受的不是自己想要的时候，恢复用.在异常捕获后重发使用
    Map<String, Object> lastCorrectReceivedMap;

    Map<String, Object> sendMap;

    private SplitedFile file;
    private long startOff = -1;
    private SplitedFile.SplitedBytes splitedBytes;

    private long fileLength;

    ClientActionController(Socket s) {
        try {
            oos = new ObjectOutputStream(s.getOutputStream());

            ois = new ObjectInputStream(s.getInputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 正常情况
     *
     * @throws SocketException
     */
    public boolean receiveAction() throws SocketException {
        Map<String, Object> receivedMap = null;
        try {
            try {
                receivedMap = (Map<String, Object>) ois.readObject();
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return receiveAction(receivedMap);
        } catch (SocketException e) {
            // TODO Auto-generated catch block
            throw e;
        }
    }

    /**
     * 情况
     *
     * @throws SocketException
     */
    public boolean receiveActionAfterError() throws SocketException {
        try {
            return receiveAction(lastCorrectReceivedMap);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            throw new SocketException("没读出来");
        }
    }

    /**
     * @return 下次应该接收的
     * @throws SocketException
     */
    private boolean receiveAction(Map<String, Object> receivedMap)
            throws SocketException {
        boolean isEnd = false;
        mReceivedMap = receivedMap;
        // 检验是不正确
        getNeedStringValue(Constants.MapKey.STATUS, Constants.STATUS.STATUS_OK);
        // 比对是不是想得到的action
        int action = getIntValue(Constants.MapKey.ACTION);

        switch (action) {
            case Constants.Action.RECEIVE_FILE_START_OFF_NEED:
                isEnd = receiveFileStartOffNeed();
                break;
            case Constants.Action.RECEIVE_FILE_HEAD_INFO_BACK:
                receiveFileHeadInfoBack();
                break;
            case Constants.Action.RECEIVE_FILE:
                break;
        }

        sendAction();

        lastCorrectReceivedMap = mReceivedMap;
        return isEnd;
    }

    private byte[] getBytesValue() throws SocketException {
        try {
            return (byte[]) mReceivedMap
                    .get(Constants.MapKey.SPLETED_FILE_BYTES);
        } catch (Exception e) {
            throw new SocketException("提取bytes[]转换错误");
        }
    }

    private boolean getBooleanValue() throws SocketException {
        try {
            return Boolean.parseBoolean(mReceivedMap.get(Constants.MapKey.IS_END).toString());
        } catch (Exception e) {
            throw new SocketException("提取isEnd(boolean)转换错误");
        }
    }

    private long getLongValue(String key) throws SocketException {
        try {
            return Long.parseLong(mReceivedMap.get(key).toString());
        } catch (Exception e) {
            throw new SocketException("提取long转换错误key=" + key);
        }
    }

    private int getIntValue(String key) throws SocketException {
        try {
            return Integer.parseInt(mReceivedMap.get(key).toString());
        } catch (Exception e) {
            throw new SocketException("提取int转换错误key=" + key);
        }
    }

    private String getStringValue(String key) throws SocketException {
        String value = (String) mReceivedMap.get(key);
        if (value == null) {
            throw new SocketException("取值错误key=" + key);
        }
        return value;
    }

    private String getNeedStringValue(String key, String needValue)
            throws SocketException {
        String value = getStringValue(key);
        if (!needValue.equals(value)) {
            throw new SocketException("得到的不是想要的key=" + key + " value=" + value
                    + " needValue=" + needValue);
        }
        return value;
    }

    private boolean receiveFileStartOffNeed() throws SocketException {
        boolean isEnd = false;
        isEnd = getBooleanValue();
        if (!isEnd) {
            startOff = getLongValue(Constants.MapKey.START_OFF);
            System.out.println(startOff);
            System.out.println(fileLength);

            splitedBytes = file.getBytes(startOff);

            sendMap = new HashMap<String, Object>();
            sendMap.put(Constants.MapKey.STATUS, Constants.STATUS.STATUS_OK);
            // 客户端 action是
            sendMap.put(Constants.MapKey.ACTION,
                    Constants.Action.RECEIVE_FILE_HEAD_INFO);
            sendMap.put(Constants.MapKey.START_OFF, startOff);
            sendMap.put(Constants.MapKey.SPLETED_FILE_LENGTH,
                    splitedBytes.length);

            MainActivity.sendMsg(MainActivity.UPDATE, startOff * 100 / fileLength);
        }
        return isEnd;
    }

    private void receiveFileHeadInfoBack() throws SocketException {

        sendMap = new HashMap<String, Object>();
        sendMap.put(Constants.MapKey.STATUS, Constants.STATUS.STATUS_OK);
        // 客户端 action是
        sendMap.put(Constants.MapKey.ACTION, Constants.Action.RECEIVE_FILE);
        sendMap.put(Constants.MapKey.SPLETED_FILE_BYTES, splitedBytes.bytes);

    }

    private void sendAction() throws SocketException {
        try {
            oos.writeObject(sendMap);
            oos.flush();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            throw new SocketException("发送错误action="
                    + sendMap.get(Constants.MapKey.ACTION).toString());
        }
    }

    public void sendHeadInfo(String filePath) throws SocketException {
        try {
            file = new SplitedFile(filePath);
            sendMap = new HashMap<String, Object>();
            sendMap.put(Constants.MapKey.STATUS, Constants.STATUS.STATUS_OK);
            sendMap.put(Constants.MapKey.ACTION,
                    Constants.Action.RECEIVE_HEAD_INFO);
            sendMap.put(Constants.MapKey.FILE_LENGTH, file.getFileLength());
            sendMap.put(Constants.MapKey.FILE_NAME,
                    filePath.substring(Constants.FILE_DIR.length()));
            sendAction();

            fileLength = file.getFileLength();
        } catch (FileNotFoundException e) {
            throw new SocketException("开始发送失败,文件没找到");
        }

    }

    public void close() {
        try {
            oos.close();
            ois.close();
            file.close();
        } catch (IOException e) {
            System.out.println("关闭出错");
        }
    }
}
